package main

import (
	"fmt"
	"time"
)

func channel()  {
	c := make(chan int)

	c <- 1
	c <- 2
	c <- 3

	n := <-c
	fmt.Println(n)
}

func channel2()  {
	c := make(chan int)

	go func() {
		for  {
			n := <-c
			fmt.Println(n)
		}
	}()

	c <- 1
	c <- 2
	c <- 3

	// 这种情况3有可能打印不出来，
	// 因为1,2,3分别往goroutine放的时候（c <- 1），
	// for中 n 一直在接收（n := <-c），
	// 所以有可能接收太快了程序结束了，fmt.Println(3)还没有执行，所以呢3没打印出来
	// time.Sleep(time.Minute) //这里用时间等待，但是这种处理只能测试用，实际开发不能这样
}

func channel3()  {

	// 创建一个数组chan
	var c [10]chan int
	for i := 0; i < 10; i++ {
		c[i] = make(chan int)
		go worker(c[i])
	}

	// 循环往chan里面放1-10
	for i := 0; i< 10; i++ {
		c[i] <- i
	}
	time.Sleep(time.Minute) //这里用时间等待，但是这种处理只能测试用，实际开发不能这样
}

// 接收chan
func worker(c chan int) {
	for  {
		fmt.Println(<-c)
	}
}

func channel4()  {

	// 创建一个数组chan
	var c [10]chan int
	for i := 0; i < 10; i++ {
		c[i] = createChan(i)
	}

	// 循环往chan里面放1-10
	for i := 0; i< 10; i++ {
		c[i] <- i
	}
}

// 返回chan int
func createChan(i int) chan int{
	c := make(chan int)
	go worker(c)
	return c
}

func bufferedChannel()  {
	c := make(chan int, 3)

	c <- 1
	c <- 2
	c <- 3
	//c <- 4  // 这里多一个就会报错
}

func bufferedChannel2()  {
	c := make(chan int, 3)

	go worker(c)

	c <- 1
	c <- 2
	c <- 3
	c <- 5
	time.Sleep(time.Minute)
}

func channelClose()  {
	c := make(chan int, 3)

	go worker(c)

	c <- 1
	c <- 2
	c <- 3
	c <- 5
	close(c)
	time.Sleep(time.Millisecond)

	// 执行结果会返回很多空或者0，因为向channel的c变量中发送1,2,3，然后close关闭了发送的chan，然而接收的那一方还在继续接收，所以打印空或者0
	// 只有等time.Sleep(time.Millisecond)过后goroutine才不会继续接收了
	//1
	//2
	//3
	//5
	//0
	//0
	//0
	//0...
}


func channelClose2()  {
	c := make(chan int, 3)

	go worker2(c)

	c <- 13
	c <- 2
	c <- 3
	close(c)
	time.Sleep(time.Millisecond)

}
// 接收chan
func worker2(c chan int) {

	for  {
		n, ok := <-c
		if !ok { // 判断一下如果没有chan了返回了
			break
		}
		fmt.Println(n)
	}
}

func channelClose3()  {
	c := make(chan int)

	go worker3(c)

	c <- 13
	c <- 2
	c <- 3
	close(c)
	time.Sleep(time.Millisecond)

}

// 接收chan 等于worker2
func worker3(c chan int) {
	for n := range c{
		fmt.Println(n)
	}
}

func main()  {
	//channel()
	//channel2()
	//channel3()
	//channel4()

	//bufferedChannel()
	//bufferedChannel2()

	//channelClose()
	//channelClose2()
	channelClose3()
}